﻿// --------------------------------------------------------------------------------------------------------------------
// <copyright file="VmTickets.cs" company="Mar3ek">
//   http://mar3ek.wordpress.com
// </copyright>
// <summary>
//   
// </summary>
// --------------------------------------------------------------------------------------------------------------------

namespace Mar3ek.HouseLight
{
    using System;
    using System.Collections.ObjectModel;
    using System.ComponentModel;
    using System.Threading;
    using System.Windows;
    using System.Windows.Input;
    using LighthouseNET;

    /// <summary>
    /// Tool windows view model
    /// </summary>
    public partial class ToolWindowViewModel
    {
        private readonly ICommand _filterCommand;
        private readonly ICommand _newTicketCommand;
        private readonly ICommand _modifyCommand;
        private readonly ICommand _deleteCommand;
        private readonly ICommand _nextPageCommand;
        private readonly ICommand _prevPageCommand;
        private readonly ICommand _showTicketHistoryCommand;

        private int _currentPage = 1;

        private ObservableCollection<Project> _projects;

        private readonly ObservableCollection<string> _searchKeywords = new ObservableCollection<string>();
        private ObservableCollection<Ticket> _tickets;

        private string _filterKeyword = string.Empty;
        private Ticket _selectedTicket;
        private bool _isHistoryViewOpen;

        private bool _isTicketsEnabled = true;

        /// <summary>
        /// Gets or sets Tickets.
        /// </summary>
        public ObservableCollection<Ticket> Tickets
        {
            get
            {
                return _tickets;
            }

            set
            {
                _tickets = value;
                OnPropertyChanged(new PropertyChangedEventArgs("Tickets"));
            }
        }

        /// <summary>
        /// Gets the filter command.
        /// </summary>
        public ICommand FilterCommand
        {
            get { return _filterCommand; }
        }

        /// <summary>
        /// Gets or sets the filter keyword.
        /// </summary>
        /// <value>
        /// The filter keyword.
        /// </value>
        public string FilterKeyword
        {
            get
            {
                return _filterKeyword;
            }

            set
            {
                _filterKeyword = value;
                OnPropertyChanged(new PropertyChangedEventArgs("FilterKeyword"));
            }
        }

        /// <summary>
        /// Gets the new ticket command.
        /// </summary>
        public ICommand NewTicketCommand
        {
            get { return _newTicketCommand; }
        }

        /// <summary>
        /// Gets or sets the selected ticket.
        /// </summary>
        /// <value>
        /// The selected ticket.
        /// </value>
        public Ticket SelectedTicket
        {
            get
            {
                return _selectedTicket;
            }

            set
            {
                _selectedTicket = value;
                OnPropertyChanged(new PropertyChangedEventArgs("SelectedTicket"));
            }
        }

        /// <summary>
        /// Gets the modify command.
        /// </summary>
        public ICommand ModifyCommand
        {
            get { return _modifyCommand; }
        }

        /// <summary>
        /// Gets the delete command.
        /// </summary>
        public ICommand DeleteCommand
        {
            get { return _deleteCommand; }
        }

        /// <summary>
        /// Gets the current page.
        /// </summary>
        public int CurrentPage
        {
            get
            {
                return _currentPage;
            }

            private set
            {
                _currentPage = value;
                OnPropertyChanged(new PropertyChangedEventArgs("CurrentPage"));
            }
        }

        /// <summary>
        /// Gets the next page command.
        /// </summary>
        public ICommand NextPageCommand
        {
            get { return _nextPageCommand; }
        }

        /// <summary>
        /// Gets the prev page command.
        /// </summary>
        public ICommand PrevPageCommand
        {
            get { return _prevPageCommand; }
        }

        /// <summary>
        /// Gets or sets a value indicating whether this instance is tickets enabled.
        /// </summary>
        /// <value>
        /// <c>true</c> if this instance is tickets enabled; otherwise, <c>false</c>.
        /// </value>
        public bool IsTicketsEnabled
        {
            get
            {
                return _isTicketsEnabled;
            }

            set
            {
                _isTicketsEnabled = value;
                OnPropertyChanged(new PropertyChangedEventArgs("IsTicketsEnabled"));
            }
        }

        /// <summary>
        /// Gets or sets a value indicating whether the history view is open.
        /// </summary>
        /// <value>
        /// <c>true</c> if this instance is history view open; otherwise, <c>false</c>.
        /// </value>
        public bool IsHistoryViewOpen
        {
            get
            {
                return _isHistoryViewOpen;
            }

            set
            {
                if (_selectedTicket == null)
                {
                    return;
                }

                _isHistoryViewOpen = value;
                OnPropertyChanged(new PropertyChangedEventArgs("IsHistoryViewOpen"));
            }
        }

        /// <summary>
        /// Gets the show ticket history command.
        /// </summary>
        public ICommand ShowTicketHistoryCommand
        {
            get { return _showTicketHistoryCommand; }
        }

        /// <summary>
        /// Gets the search keywords.
        /// </summary>
        public ObservableCollection<string> SearchKeywords
        {
            get { return _searchKeywords; }
        }

        /// <summary>
        /// Tries to retrieve the previous page of ticktes
        /// </summary>
        /// <param name="parameter">The parameter.</param>
        private void PrevPage(object parameter)
        {
            if ((int)parameter <= 1)
            {
                return;
            }

            try
            {
                Tickets = new ObservableCollection<Ticket>(_api.GetTickets(SelectedProject.Id, _filterKeyword ?? "state:all", _currentPage - 1));
                CurrentPage--;
            }
            catch (LighthouseResponseException ex)
            {
                MessageBox.Show(
                    ex.Message,
                    "HouseLight",
                    MessageBoxButton.OK,
                    MessageBoxImage.Error);
            }
            catch (LighthouseServerException ex)
            {
                MessageBox.Show(
                    string.Format("A communication error was encountered. Check your internet connection and try again.\nIf the problem persists, contact the plugin developer.\nError details follow:\n\n{0}", ex.Message),
                    "HouseLight",
                    MessageBoxButton.OK,
                    MessageBoxImage.Error);
            }
        }

        /// <summary>
        /// Tries to retrieve the next page of tickets
        /// </summary>
        /// <param name="parameter">The parameter.</param>
        private void NextPage(object parameter)
        {
            try
            {
                var tickets = _api.GetTickets(SelectedProject.Id, _filterKeyword ?? "state:all", _currentPage + 1);
                if (tickets.Count > 0)
                {
                    Tickets = new ObservableCollection<Ticket>(tickets);
                    CurrentPage++;
                }
            }
            catch (LighthouseResponseException ex)
            {
                MessageBox.Show(
                    ex.Message,
                    "HouseLight",
                    MessageBoxButton.OK,
                    MessageBoxImage.Error);
            }
            catch (LighthouseServerException ex)
            {
                MessageBox.Show(
                    string.Format("A communication error was encountered. Check your internet connection and try again.\nIf the problem persists, contact the plugin developer.\nError details follow:\n\n{0}", ex.Message),
                    "HouseLight",
                    MessageBoxButton.OK,
                    MessageBoxImage.Error);
            }
        }

        /// <summary>
        /// Deletes a ticket
        /// </summary>
        /// <param name="parameter">The parameter.</param>
        private void DeleteTicketAction(object parameter)
        {
            if (parameter == null)
            {
                return;
            }

            var ticket = (Ticket)parameter;

            var result = MessageBox.Show("Do you really want to delete the selected ticket? This action cannot be undone.", "HouseLight", MessageBoxButton.YesNo, MessageBoxImage.Question);

            if (result != MessageBoxResult.Yes)
            {
                return;
            }

            try
            {
                _api.DeleteTicket(SelectedProject.Id, ticket.Number);
                FilterAction(_filterKeyword ?? "state:all");
            }
            catch (LighthouseResponseException ex)
            {
                MessageBox.Show(
                    ex.Message,
                    "HouseLight",
                    MessageBoxButton.OK,
                    MessageBoxImage.Error);
            }
            catch (LighthouseServerException ex)
            {
                MessageBox.Show(
                    string.Format("A communication error was encountered. Check your internet connection and try again.\nIf the problem persists, contact the plugin developer.\nError details follow:\n\n{0}", ex.Message),
                    "HouseLight",
                    MessageBoxButton.OK,
                    MessageBoxImage.Error);
            }
        }

        /// <summary>
        /// Open the ticket modification window
        /// </summary>
        /// <param name="parameter">The parameter.</param>
        private void ModifyTicketAction(object parameter)
        {
            if (parameter == null)
            {
                return;
            }

            var w = new wNewTicket(_api, (Ticket)parameter, SelectedProject, _milestones, Users) { Owner = _mainWindow };
            w.Closed += TicketWindowClosed;
            w.Show();
        }

        /// <summary>
        /// Opens the new ticket window
        /// </summary>
        /// <param name="parameter">The parameter.</param>
        private void NewTicketAction(object parameter)
        {
            if (parameter == null)
            {
                return;
            }

            var w = new wNewTicket(_api, (Project)parameter, _milestones, Users) { Owner = _mainWindow };
            w.Closed += TicketWindowClosed;
            w.Show();
        }

        /// <summary>
        /// Handles the Closed event of a wNewTicket window
        /// </summary>
        /// <param name="sender">The sender.</param>
        /// <param name="e">The <see cref="System.EventArgs"/> instance containing the event data.</param>
        private void TicketWindowClosed(object sender, EventArgs e)
        {
            if (((wNewTicket)sender).Result)
            {
                RefreshTickets();
            }
        }

        /// <summary>
        /// Filters the tickets.
        /// </summary>
        /// <param name="parameter">The parameter.</param>
        private void FilterAction(object parameter)
        {
            var t = new Thread(() =>
            {
                if (parameter == null)
                {
                    return;
                }

                var stringValue = parameter.ToString();
                FilterKeyword = stringValue;
                SelectedTabIndex = 0;
                Tickets = stringValue == "state:all" ? new ObservableCollection<Ticket>(_api.GetTickets(_selectedProject.Id)) : new ObservableCollection<Ticket>(_api.GetTickets(_selectedProject.Id, stringValue));
            }) { IsBackground = true, Name = "Filter tickets thread" };
            t.Start();
        }

        /// <summary>
        /// Refreshes the tickets.
        /// </summary>
        private void RefreshTickets()
        {
            var t = new Thread(() =>
            {
                try
                {
                    var ticks = new ObservableCollection<Ticket>(_api.GetTickets(_selectedProject.Id, _filterKeyword ?? "state:all", _currentPage, 10));
                    var temp = new ObservableCollection<Ticket>();
                    foreach (var ti in ticks)
                    {
                        temp.Add(_api.GetTicket(ti.ProjectId, ti.Number));
                    }

                    Tickets = temp;
                }
                catch (Exception)
                {
                    IsTicketsEnabled = false;
                }
            }) { IsBackground = true, Name = "Refresh tickets thread" };
            t.Start();
        }
    }
}
